<?php
namespace app\data_magic\logic;

use app\data_magic\widget\FormWidget;
use app\data_magic\widget\ListWidget;
use app\data_magic\widget\TabsWidget;
use app\data_magic\widget\FilterWidget;
use think\Db;
use app\data_magic\struct\Input;
use app\data_magic\struct\Result;
use app\data_magic\data\Action;

/**
 * 数据列表
 */
class DataList
{
    /**
     * 依赖注入
     * @var Interpreter $interpreter 解释器
     * @var Input $input 输入
     * @var Result $result 输出
     * @param Interpreter $interpreter 解释器
     * @param Input $input 输入
     * @param Result $result 输出
     */
    public $interpreter;
    public $input;
    public $result;
    public function __construct($interpreter,$input,$result)
    {
        $this->interpreter=$interpreter;
        $this->input=$input;
        $this->result=$result;
    }
    /**
     * 分发
     * @var array[] $typeMap 方法-类型 映射
     *  "方法名"=>["操作类型","目标类型","数据绑定"]
     */
    public $typeMap=[
        "create_form_nope"=>"showCreateForm",
        "create_post_nope"=>"createItem",
        "create_form_single"=>"showCopyForm",
        "remove_exec_single"=>"deleteItem",
        "remove_exec_multi"=>"deleteMultiItem",
        "update_form_single"=>"showEditForm",
        "update_post_single"=>"editItem",
        "search_show_where"=>"showList",
        "search_show_single"=>"showItem",
    ];
    public function dispath(){
        $action=$this->result->action;
        $action_str=$action->action_type."_".$action->target_type."_".$action->data_type;
        foreach($this->typeMap as $key => $func){
            if($key === $action_str){
                return call_user_func([$this,$func]);
            }
        }
        return false;
    }
    /**
     * @var string $error 错误信息
     */
    protected $error="";

    /**
     * 数据保存之前进行预处理
     * @param FieldData[] $fields 字段设置
     * @param array $item 单条数据
     * @param array $params 操作中设置的键值对
     */
    public function beforeSave($fields,$item,$params)
    {
        $writable_fields=[];
        $exist_fields=[];
        foreach($fields as $field){
            if($field->writable){
                $writable_fields[]=$field->name;
            }
            $exist_fields[]=$field->name;
        }
        //过滤掉不可写的字段
        $data=[];
        foreach($item as $key => $value){
            if(in_array($key,$writable_fields)){
                $data[$key]=$value;
            }
        }
        $data=$this->convertToSaveFormat($fields,$data);
        $data=array_merge($data,$params);
        //过滤掉不存在的字段
        $item=[];
        foreach($data as $key => $value){
            if(in_array($key,$exist_fields)){
                $item[$key]=$value;
            }
        }
        return $item;
    }
    
    protected function createFormWidget($data_item)
    {
        $form=new FormWidget();
        if(!$this->result->bindAction){
            $this->error="未指定提交数据的操作";
            return false;
        }
        $form->bind_action=$this->result->bindAction;
        $form->fields=$this->result->fields;
        $form->data_item=$data_item;
        return $form;
    }
    protected function createListWidget()
    {
        $action=$this->result->action;
        $list=new ListWidget();
        $list->fields=$this->result->fields;
        $list->setActions($this->result->linkActions);
        return $list;
    }
    protected function createPageResult($widget)
    {
        $action=$this->result->action;
        $result=$this->result;
        $result->is_page=true;

        if($widget){
            $result->widgets[]=$widget;
        }
        else{
            $result->status=false;
            $result->message=$this->error;
        }

        $tabs=new TabsWidget();
        $tabs->setActions($result->linkActions);
        $tabs->setCurrentAction($action->id);
        $result->widgets[]=$tabs;

        $filter=new Filter();
        $filter_widget=$filter->getFilterWidget($result->linkActions,$result->filters,$this->input->where);
        if($filter_widget){
            $result->widgets[]=$filter_widget;
        }
        return $result;
    }
    protected function createExecResult($status)
    {
        $result=$this->result;
        $result->is_page=false;
        $result->status=$status;
        if(!$status){
            $result->message=$this->error();
        }
        return $result;
    }
    /**
     * 新建，显示创建数据的表单
     * 创建数据前读取预先设置的参数,比如用户id和通过URL传递的关联的数据的id,并且将这些数据设置为不可编辑状态
     */
    public function showCreateForm()
    {
        $result=$this->result;
        $item=$this->input->data;
        $keys=array_keys($item);
        if($result->userIdField){
            $item[$result->userIdField]=$result->userId;
            $keys[]=$result->userIdField;
        }
        foreach($result->fields as $index=>$field){
            if(in_array($field->name,$keys)){
                $field->writable=false;
            }
        }
        $widget=$this->createFormWidget($item);
        return $this->createPageResult($widget);
    }
    /**
     * 复制，复制已有数据并且编辑
     */
    public function showCopyForm()
    {
        $result=$this->result;
        $item=Db::table($result->table->name)->where($result->primaryKey."=".$this->input->pks)->find();
        $widget=$this->createFormWidget($item);
        return $this->createPageResult($widget);
    }
    /**
     * 插入
     */
    public function createItem()
    {
        $result=$this->result;
        $params=$result->action->getActionParams();
        $field_logic=new Field();
        $data=$field_logic->beforeSave($result->fields,$this->input->data,$params);
        $current_time=time();
        if($result->userIdField){
            $data[$result->userIdField] = $result->userId;
        }
        if($result->createTimeField){
            $data[$result->createTimeField]=$current_time;
        }
        if($result->updateTimeField){
            $data[$result->updateTimeField]=$current_time;
        }
        $res=Db::table($this->result->table->name)->insert($data);
        if($res===0){
            $this->error="插入数据失败";
            return $this->createExecResult(false);
        }
        elseif($res===false){
            $this->error="插入数据错误";
            return $this->createExecResult(false);
        }
        return $this->createExecResult(true);
    }
    /**
     * 删除
     */
    public function deleteItem()
    {
        $result=$this->result;
        $result->where[]=$result->primaryKey."=".$this->input->pks;
        $where="(".join(") AND (",$result->where).")";
        $res=Db::table($result->table->name)->where($where)->delete();
        $res = $res ? true : false ;
        return $this->createExecResult($result);
    }
    /**
     * 删除多项
     */
    public function deleteMultiItem()
    {
        $result=$this->result;
        $result->where[]=$result->primaryKey." in (".$this->input->pks.")";
        $where="(".join(") AND (",$result->where).")";
        $res=Db::table($result->table->name)->where($where)->delete();
        $res = $res===false ? false : true ;
        return $this->createExecResult($res);
    }
    /**
     * 编辑，显示编辑表单
     */
    public function showEditForm()
    {
        $result=$this->result;
        $result->where[]=$result->primaryKey."=".$this->input->pks;
        $where="(".join(") AND (",$result->where).")";
        $item=Db::table($result->table->name)->where($where)->find();
        $widget=$this->createFormWidget($item);
        return $this->createPageResult($widget);
    }
    /**
     * 更新
     */
    public function editItem()
    {
        $result=$this->result;
        $params=$result->action->getActionParams();
        $field_logic=new Field();
        $data=$field_logic->beforeSave($result->fields,$this->input->data,$params);
        if($result->updateTimeField){
            $data[$result->updateTimeField]=time();
        }
        $result->where[]=$result->primaryKey."=".$this->input->pks;
        $where="(".join(") AND (",$result->where).")";
        $res=Db::table($result->table->name)->where($where)->update($data);
        $res = $res ? true : false ;
        return $this->createExecResult($res);
    }
    /**
     * 列表，显示列表
     */
    public function showList()
    {
        $result=$this->result;
        $filter=new Filter();
        $result->where=$filter->getWhere($result->table->id,$result->fields,$this->input->where);
        $widget=$this->createListWidget();
        return $this->createPageResult($widget);
    }
    /**
     * 详情，显示单项数据
     */
    public function showItem()
    {

    }
}
